home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tar316.zip / QICFACE.C < prev    next >
Text File  |  1980-07-24  |  8KB  |  285 lines

  1. #include <stdio.h>
  2. #include "sysup.h"
  3. #ifdef MSDOS
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7.  
  8. #include "modern.h"
  9. #include "define.h"
  10. #include "qic02.h"
  11.  
  12. #define MAXLEX 8
  13. #define SKIP_RESET 0x80
  14.  
  15. static int board_type = UNUSED;
  16. static struct init_data id = { UNUSED, UNUSED, UNUSED };
  17. static int no_rewind = FALSE;
  18. static BYTE cmdset = 0;
  19. static struct { int nqic; BYTE tracks, command; } qiclist[] = {
  20.    { 11,  4,  Q2_QIC11  }, { 24,  9,  Q2_QIC24  },
  21.    { 120, 15, Q2_QIC120 }, { 150, 18, Q2_QIC150 },
  22.    { 300, -1, 0x2A      }, { 2100,-1, 0x2A      },
  23.    { 600, -1, 0x2B      }, { 2200,-1, 0x2B      },
  24. };
  25.  
  26. int qparse(char *s)
  27. {
  28.    static char already[] = "tape fromat already defined";
  29.    char lex[MAXLEX+1], *errmsg;
  30.    register i, k;
  31.  
  32.    for (i=0; i<MAXLEX && *s && *s!='.'; i++) {
  33.       if (*s == ':' || *s == ';' || *s == ',') goto test_name;
  34.       lex[i] = *s++;
  35.    }
  36.    return FALSE;
  37. test_name:
  38.    lex[i] = '\0';
  39.    if ((board_type=streamer('?', lex, 0)) < 0) return FALSE;
  40.  
  41.    id.base_address = UNUSED;
  42.    id.dma_number   = UNUSED;
  43.    id.irq_number   = UNUSED;
  44.    no_rewind       = FALSE;
  45.  
  46.    while (*++s) {
  47.       for (i=0; i<=MAXLEX; ++i, s++) {
  48.          if      (*s >= 'A' && *s <= 'Z') lex[i] = *s | ('z'^'Z');
  49.          else if (*s >= 'a' && *s <= 'z') lex[i] = *s;
  50.          else break;
  51.       }
  52.       if (i < 1 || i > MAXLEX) {
  53.          errmsg = "device parameter error"; goto error;
  54.       }
  55.       lex[i] = '\0'; /* for diagnostic printing */
  56.       if (!strncmp("norewind", lex, i)) {
  57.          no_rewind = TRUE;
  58.       } else if (!strncmp("qic", lex, i)) {
  59.          if (cmdset) {
  60.             errmsg = already; goto error;
  61.          }
  62.          if (*s == '-') {
  63.             ++s;
  64.          } else {
  65.             if (*s == ':') ++s;
  66.             if (*s == '=') ++s;
  67.          }
  68.          if (*s >= '1' && *s <= '9') {
  69.             k = 0; i = 0;
  70.             do {
  71.                k = (*s++ - '0') + 10*k;
  72.             } while (++i < 5 && *s >= '0' && *s <= '9');
  73.             if (i < 5) {
  74.                for (i=0; i<dimof(qiclist); i++) {
  75.                   if (qiclist[i].nqic == k) {
  76.                      cmdset = qiclist[i].command; break;
  77.                   }
  78.                }
  79.             }
  80.          }
  81.          if (!cmdset) {
  82.             errmsg = "invalid QIC number"; goto error;
  83.          }
  84.       } else {
  85.          if (*s == ':') ++s;
  86.          if (*s == '=') ++s;
  87.          if (strncmp("base", lex, i) == 0) {
  88.             for (id.base_address=0, i=0; i<5; ++i, s++) {
  89.                register j = '0';
  90.                if      (*s>='A' && *s<='F') j = 'A' - 10;
  91.                else if (*s>='a' && *s<='f') j = 'a' - 10;
  92.                else if (*s <'0' || *s >'9') break;
  93.                id.base_address = (id.base_address << 4) | (*s - j);
  94.             }
  95.             if (i<1 || i>4) {
  96.                errmsg = "invalid base address"; goto error;
  97.             }
  98.             if (*s == 'h' || *s == 'H') ++s;
  99.          } else if (strncmp("dma", lex, i) == 0) {
  100.             if (*s<'0' || *s>'7') {
  101.                errmsg = "invalid DMA channel number"; goto error;
  102.             }
  103.             id.dma_number = *s++ & 7;
  104.          } else if (strncmp("irq", lex, i) == 0) {
  105.             for (id.irq_number=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) {
  106.                id.irq_number = 10*id.irq_number + *s - '0';
  107.             }
  108.             if (i<1 || i>2 || id.irq_number > 15) {
  109.                errmsg = "invalid IRQ number"; goto error;
  110.             }
  111.          } else if (strncmp("tracks", lex, i) == 0) {
  112.             if (cmdset) {
  113.                errmsg = already; goto error;
  114.             }
  115.             for (k=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) {
  116.                k = (*s - '0') + 10*k;
  117.             }
  118.             if (i > 0 && i < 3) {
  119.                for (i=0; i<dimof(qiclist); i++) {
  120.                   if (qiclist[i].tracks == k) {
  121.                      cmdset = qiclist[i].command; break;
  122.                   }
  123.                }
  124.             }
  125.             if (!cmdset) {
  126.                errmsg = "invalid number of tracks"; goto error;
  127.             }
  128.          } else {
  129.             (void)fprintf(stderr,"Tar: unknown parameter \'%s\'\n",lex);
  130.             return ERROR;
  131.          }
  132.       }
  133.       if (*s == '\0') break;
  134.       if (*s != ',' && *s != ':' && *s != '.') {
  135.          (void)fprintf(stderr,"Tar: invalid character after \'%s\'\n",lex);
  136.          return ERROR;
  137.       }
  138.    }
  139.    if (id.base_address == UNUSED) {
  140.       errmsg = "base address must be specified"; goto error;
  141.    }
  142.    if (!cblock) cblock = 1;
  143.    return TRUE;
  144. error:
  145.    (void)fprintf(stderr,"Tar: %s\n", errmsg);
  146.    return ERROR;
  147. }
  148.  
  149. static void qerror(int k)
  150. {
  151.    if (k < 0) {
  152.       (void)fprintf(stderr, "Tar: %s\n", strerror(errno));
  153.    } else if (k < qic02_nerr) {
  154.       (void)fprintf(stderr, "Tar: %s\n", qic02_errlist[k]);
  155.    } else {
  156.       (void)fprintf(stderr, "Tar: error #%d\n", k);
  157.    }
  158. }
  159.  
  160. int qbegin(void)
  161. {
  162.    register k;
  163.  
  164.    if (no_rewind) board_type |= SKIP_RESET;
  165.    if ((k=streamer('o', &id, board_type)) != 0) {
  166.       if (k != CTE_FAULT || errno != EINVDAT) goto error;
  167.       (void)fprintf(stderr, "Tar: unsupported hardware configuration\n");
  168.       return k;
  169.    }
  170.    if (setdrive) {
  171.       if ((k=streamer('i',NULL,(1<<ndrive)&15/*|Q2_SELECT*/))!=0) goto error;
  172.    }
  173.    if (!no_rewind) {
  174.       if ((k=c_flag ? streamer('i',NULL,Q2_ERASE) : streamer('n',NULL,0))!=0)
  175.          goto error;
  176.       if (cmdset) {/* select tape format */
  177.          if ((k=streamer('i', NULL, cmdset)) != 0) goto error;
  178.       }
  179.    }
  180.    return 0;
  181. error:
  182.    qerror(k);
  183.    return k;
  184. }
  185.  
  186. void qend(void)
  187. {
  188.    if (!no_rewind) streamer('n',NULL,0);
  189.    streamer('c',NULL,0);
  190. }
  191.  
  192. static void ioerror(unsigned mask)
  193. {
  194.    register k;
  195.    struct qic02_word_status s;
  196.    extern int ct_errbit(unsigned);
  197.  
  198.    k = streamer('t', &s, 0);
  199.    if (k >= 0 && k <= CTE_BUSY) {
  200.       k = ct_errbit(mask & s.status);
  201.    }
  202.    qerror(k);
  203. }
  204.  
  205. /* Interface routines */
  206. int qread(char *buf, register int n)
  207. {
  208.    if (n & (BLKSIZE-1)) return -1;
  209.    if (streamer('r', buf, n) != n) {
  210.       ioerror(~(Q2E_BOM|Q2E_WRP));
  211.       return -1;
  212.    }
  213.    return n;
  214. }
  215.  
  216. int qwrite(char *buf, register int n)
  217. {
  218.    n = (BLKSIZE-1 + n) & ~(BLKSIZE-1);
  219.    if (streamer('w', buf, n) != n) {
  220.       ioerror(~Q2E_BOM);
  221.       return -1;
  222.    }
  223.    return n;
  224. }
  225.  
  226. int qback(n)
  227. register n;
  228. {
  229.    register j, k;
  230.    for (j=(n+cblock-1)/cblock; j; j--)
  231.       if ((k=streamer('i',NULL,Q2_REVERSE)) != 0) {
  232.          qerror(k); return -1;
  233.       }
  234.    return n;
  235. }
  236. #endif
  237.  
  238. char *getbuf(length)
  239. int length;
  240. {
  241.    register char *ptr;
  242. #ifdef MSDOS
  243.    int dw; /* size of DMA word */
  244.  
  245.    dw = id.dma_number & ~7 ? 0 : 1 + (id.dma_number >> 2);
  246.    ptr = malloc(length);
  247.    if (!ptr) {
  248.       (void)fprintf(stderr, "Tar: not enough memory\n");
  249.    } else if (dw > 0) {
  250.       long a; register s;
  251.  
  252.       a = ptr2abs(ptr);
  253.       s = dw + 15; /* shift factor to get DMA page number */
  254.       /* Compare DMA pages */
  255.       if ((a >> s) != ((a+length-1) >> s)) {
  256.       /* Attempt to get DMA page-aligned buffer assumes: */
  257.       /*  - length is not greater than half of DMA page; */
  258.       /*  - malloc() heap is unfragmented.               */
  259.          register void *tmp;
  260.  
  261.          tmp = ptr; ptr = malloc(length); free(tmp);
  262.          if (!ptr) {
  263.             (void)fprintf(stderr, "Tar: no memory to align buffer\n");
  264.             return (void *)0;
  265.          }
  266.          a = ptr2abs(ptr);
  267.          if ((a >> s) != ((a+length-1) >> s)) {
  268.             (void)fprintf(stderr, "Tar: fail to align buffer\n");
  269.             free(ptr); return (void *)0;
  270.          }
  271.       }
  272.       if (a & (dw - 1)) {
  273.          (void)fprintf(stderr, "Tar: DMA buffer is not word-aligned\n");
  274.          free(ptr); return (void *)0;
  275.       }
  276.    }
  277.    return ptr;
  278. #else
  279.    extern char *malloc();
  280.    ptr = malloc(length);
  281.    if (!ptr) (void)fprintf(stderr, "Tar: not enough memory\n");
  282.    return ptr;
  283. #endif
  284. }
  285.